package com.cq.androidtools.recycleview2

import android.content.Context
import android.os.Handler
import android.text.Editable
import android.text.TextWatcher
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.cq.androidtools.R
import com.cq.androidtools.recycleview.table.TableDataBean
import com.cq.androidtools.recycleview.base.BaseViewHolder
import com.cq.base.recycleview.base.BaseRVMultiTypeDiffAdapter
import com.cq.base.recycleview.base.BaseRecycleViewDiffAdapter
import com.cq.base.utils.isTouchPointInView
import kotlinx.coroutines.runBlocking

/**
 * 作者: CQ
 * 日期: 2021-08-03
 * 说明:
 */
class GridRecycleView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) {

    // 头部列表
    private lateinit var recyclerViewTop: RecyclerView

    // 左侧列表
    private lateinit var recyclerViewLeft: RecyclerView

    // 中间列表
    private lateinit var recyclerViewContent: RecyclerView

    // 头部列表适配器
    private var adapterTop = AdapterCommon()

    // 左侧列表适配器
    private var adapterLeft = AdapterCommon()

    // 中间列表适配器
    private var adapterContent = AdapterCommon()

    // 头部列表数据（横向线行）
    private var listDataTop = mutableListOf<TableDataBean>()

    // 左侧列表数据（纵向线行）
    private var listDataLeft = mutableListOf<TableDataBean>()

    // 中间列表数据（横向网格）
    private var listDataContent = mutableListOf<TableDataBean>()

    // 是否是顶部recycleView移动
    var isIntoTop = false

    // 是否是中间recycleView移动
    var isIntoContent = false

    // 是否是左边recycleVIew移动
    var isIntoLeft = false

    init {
        initView(context)
    }

    private fun initView(context: Context?) { // 加载布局，获取view总布局
        val view = View.inflate(context!!, R.layout.grid_recycleview2, this) // 头部列表
        recyclerViewTop = view.findViewById(R.id.recyclerView_top) // 左侧列表
        recyclerViewLeft = view.findViewById(R.id.recyclerView_left) // 中间列表
        recyclerViewContent = view.findViewById(R.id.recyclerView_content) // 滑动控件
        val nestedScrollView = view.findViewById<NestedScrollView>(R.id.nestedScrollView)

        // 头部列表设置
        // 定义一个线性布局
        val linearLayoutManager = LinearLayoutManager(context) // 设置横向
        linearLayoutManager.orientation = RecyclerView.HORIZONTAL // 头部列表设置布局器
        recyclerViewTop.layoutManager = linearLayoutManager // 定义一个适配器
        recyclerViewTop.adapter = adapterTop // 头部列表增加一个滑动监听
        recyclerViewTop.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy) // 滑动的是头部列表
                if (isIntoTop && !isIntoLeft && !isIntoContent) { // 头部列表滑动时，关联中间列表同步滑动
                    recyclerViewContent.scrollBy(dx, dy)
                }
            }
        })

        // 左侧列表设置
        // 定义一个线性布局
        val linearLayoutManagerLeft = LinearLayoutManager(context) // 设置纵向
        linearLayoutManagerLeft.orientation = RecyclerView.VERTICAL // 左侧列表设置布局器
        recyclerViewLeft.layoutManager = linearLayoutManagerLeft // 定义一个适配器
        recyclerViewLeft.adapter = adapterLeft // 左侧列表增加一个滑动监听

        recyclerViewLeft.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy) // 滑动的是左侧列表
                if (!isIntoTop && isIntoLeft && !isIntoContent) { // 头部列表滑动时，关联中间列表同步滑动，由于中间列表上下滑动是NestedScrollView控制的，所以滑动NestedScrollView
                    Log.e("recyclerViewLeft", "dy = $dy; ")
                    nestedScrollView.scrollBy(dx, dy)
                }
            }
        })

        // 中间列表设置
        val gridLayoutManager = GridLayoutManager(context, 3)  // 定义一个网格布局器
        gridLayoutManager.orientation = RecyclerView.HORIZONTAL // 设置网格滑动方向
        recyclerViewContent.layoutManager = gridLayoutManager // 管理布局器
        recyclerViewContent.adapter = adapterContent // 列表关联适配器
        // 中间列表设置滑动监听（横向滑动）
        recyclerViewContent.addOnScrollListener(object : RecyclerView.OnScrollListener() {

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy) // 滑动的是中间列表
                Log.e("------", "dx = $dx")
                if (!isIntoTop && !isIntoLeft && isIntoContent) { // 中间列表横向滑动时，关联头部列表横向滑动
                    recyclerViewTop.scrollBy(dx, dy)
                }
            }
        })

        // 中间列表的纵向滑动控件设置滑动监听
        nestedScrollView.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, scrollX, scrollY, oldScrollX, oldScrollY -> // 滑动的是中间列表
            Log.e("nestedScrollView", "dy = ${scrollY - oldScrollY}; scrollY = $scrollY; oldScrollY = $oldScrollY; ")
            if (!isIntoTop && !isIntoLeft && isIntoContent) { // 中间列表纵向滑动时，关联左侧列表纵向滑动
                recyclerViewLeft.scrollBy(scrollX - oldScrollX, scrollY - oldScrollY)
            }
        })
    }

    // 监听手指按下，获取按下的位置，判断按下的位置属于哪个区域
    override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
        when (event!!.action) {
            MotionEvent.ACTION_DOWN -> {
                isIntoTop = recyclerViewTop.isTouchPointInView(event.rawX.toInt(), event.rawY.toInt())
                isIntoLeft = recyclerViewLeft.isTouchPointInView(event.rawX.toInt(), event.rawY.toInt())
                isIntoContent = recyclerViewContent.isTouchPointInView(event.rawX.toInt(), event.rawY.toInt()) // 横向或者纵向移动时，布局移动，可以导致按下的位置可能也在中间布局，
                if (isIntoTop || isIntoLeft) {
                    isIntoContent = false
                }
            }
        }
        return super.dispatchTouchEvent(event)
    }

    fun setDataTop(list: MutableList<TableDataBean>) {
        listDataTop = list
        val topBean = TableDataBean()
        topBean.type = 0
        topBean.gg1dm = "合计"
        listDataTop.add(topBean)
        adapterTop.onAutoData(listDataTop)
    }

    fun setDataLeft(list: MutableList<TableDataBean>) {
        listDataLeft = list
        val leftBean = TableDataBean()
        leftBean.type = 1
        leftBean.gg2dm = "合计"
        listDataLeft.add(leftBean)
        adapterLeft.onAutoData(listDataLeft)
    }

    fun setDataContent(list: MutableList<TableDataBean>) {
        listDataContent = list
        val map = mutableMapOf<String, Int>()
        val size = listDataLeft.size * listDataTop.size // 3 * 3 = 9
        for (i in 0 until size) {
            if (listDataContent[i].gg1dm != "合计") {
                if (map.containsKey(listDataContent[i].gg1dm)) {
                    map[listDataContent[i].gg1dm] = map[listDataContent[i].gg1dm]!! + listDataContent[i].value
                } else {
                    map[listDataContent[i].gg1dm] = listDataContent[i].value
                }
                if (map.containsKey(listDataContent[i].gg2dm)) {
                    map[listDataContent[i].gg2dm] = map[listDataContent[i].gg2dm]!! + listDataContent[i].value
                } else {
                    map[listDataContent[i].gg2dm] = listDataContent[i].value
                }
            }
            val contentBean = TableDataBean()
            contentBean.type = 3
            if (i < listDataLeft.size * (listDataTop.size - 1) && i % 3 == 1) {
                contentBean.gg1dm = listDataContent[i].gg1dm
                contentBean.gg2dm = "合计"
                contentBean.value = map[listDataContent[i].gg1dm]!!
                listDataContent.add(i + 1, contentBean)
            } else if (i == size - 1) {
                listDataContent[i].position = i
                break
            } else if (i >= listDataLeft.size * (listDataTop.size - 1) - 1) {
                val pos = i - (listDataLeft.size * (listDataTop.size - 1) - 1)
                contentBean.gg1dm = "合计"
                contentBean.gg2dm = listDataLeft[pos].gg2dm
                contentBean.value = map[listDataLeft[pos].gg2dm]!!
                listDataContent.add(i + 1, contentBean)
            }
            listDataContent[i].position = i
        }
        val recycledViewPool = recyclerViewContent.recycledViewPool
        recycledViewPool.setMaxRecycledViews(0, listDataContent.size)
        (recyclerViewContent.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
        adapterContent.onAutoData(listDataContent)
    }

}


class AdapterTop(list: MutableList<String>, context: Context) : BaseRecycleViewDiffAdapter<String>(list, context) {
    override fun getInflate(): Int {
        return R.layout.item_gird_text
    }

    override fun bindData(holder: BaseViewHolder, data: String, position: Int) {
        holder.getTextView(R.id.item_grid_text).text = data
    }
}

class AdapterCommon : BaseRVMultiTypeDiffAdapter<TableDataBean>() {

    companion object {
        private const val ITEM_TYPE_TOP = 0
        private const val ITEM_TYPE_LEFT = 1
        private const val ITEM_TYPE_CONTENT = 2
        private const val ITEM_TYPE_SUM = 3
    }

    private var isRecyc = true

    override fun getItemViewType(position: Int): Int {
        return getItem(position).type
    }

    override fun onCreateMultiViewHolder(parent: ViewGroup, viewType: Int): View {
        return when (viewType) {
            ITEM_TYPE_TOP -> loadLayout(R.layout.item_gird_text, parent)
            ITEM_TYPE_LEFT -> loadLayout(R.layout.item_gird_text, parent)
            ITEM_TYPE_CONTENT -> loadLayout(R.layout.item_gird_edit, parent)
            ITEM_TYPE_SUM -> loadLayout(R.layout.item_gird_text, parent)
            else -> loadLayout(R.layout.item_gird_text, parent)
        }
    }

    override fun onBindViewHolder(holder: MultiTypeViewHolder, item: TableDataBean, position: Int) {
        when (item.type) {
            ITEM_TYPE_TOP -> holder.getTextView(R.id.item_grid_text).text = item.gg1dm
            ITEM_TYPE_LEFT -> holder.getTextView(R.id.item_grid_text).text = item.gg2dm
            ITEM_TYPE_CONTENT -> {
                holder.getTextView(R.id.item_grid_edit).text = item.value.toString()
                holder.getTextView(R.id.item_grid_edit).setTag(R.id.RecyclerView_pos, position)
                holder.getTextView(R.id.item_grid_edit).setTag(R.id.RecyclerView_item, holder.getTextView(R.id.item_grid_edit))
                holder.getTextView(R.id.item_grid_edit).addTextChangedListener(object : TextWatcher {
                    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                    }

                    override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                    }

                    override fun afterTextChanged(p0: Editable?) {
                        if (isRecyc) {
                            val pos = holder.getTextView(R.id.item_grid_edit).getTag(R.id.RecyclerView_pos) as Int
                            getData()[pos].value = p0!!.toString().toInt()
                            isRecyc = false
                            Handler().post {
                                runBlocking {
                                    notifyItemChanged(pos)
                                    isRecyc = true
                                }
                            }
                        }
                    }
                })
            }
            ITEM_TYPE_SUM -> {
                holder.getTextView(R.id.item_grid_text).text = item.value.toString()
            }
        }
    }

    override fun areContentsTheSame(oldItem: TableDataBean, newItem: TableDataBean, oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldItemPosition == newItemPosition
    }

    override fun areItemsTheSame(oldItem: TableDataBean, newItem: TableDataBean): Boolean {
        return oldItem.value == newItem.value
    }

    override fun getItemId(position: Int): Long {
        return getData()[position].position.toLong()
    }



}
